package rpc_1.Server;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rpc_1.Impl.HelloServiceImpl;
import rpc_1.interfaces.HelloService;
import rpc_1.object.RpcRequest;
import rpc_1.object.RpcResponse;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class RpcServer {
    //用线程池来进行具体调用逻辑处理（即作为worker线程）
    private final ExecutorService threadPool;
    private static final Logger logger= LoggerFactory.getLogger(RpcServer.class);

    public RpcServer(){
        threadPool= Executors.newFixedThreadPool(2);
    }

    //服务端注册一个服务
    //当有连接建立，把建立连接后的具体逻辑交给worker线程处理
    public void register(Object service,int port){
        try {
            ServerSocket serverSocket= new ServerSocket();
            serverSocket.bind(new InetSocketAddress("localhost",port));
            logger.info("server is strting--");
            Socket socket;
            //阻塞，等待连接建立
            while ((socket=serverSocket.accept())!=null){
                logger.info("client connect success! :ip:"+socket.getInetAddress());
                //有连接建立，把连接交给worker线程处理
                threadPool.execute(new Worker(socket,service));
            }
        } catch (IOException e) {
            e.printStackTrace();
            logger.info("error when connecting!");
        }
    }

    class Worker implements Runnable{
        private Socket socket;
        private Object service;
        public Worker(Socket socket, Object service) {
            this.socket=socket;
            this.service=service;
        }

        @Override
        public void run() {
            try {
                ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
                //等待获取消息
                RpcRequest rpcRequest = (RpcRequest)objectInputStream.readObject();
                //得到了消息，通过反射调用，得到相应结果
                Method method = service.getClass().getMethod(rpcRequest.getMethodName(),rpcRequest.getParamTypes());
                String res =(String) method.invoke(service, rpcRequest.getParameters());
                //将结果封装成rpcResponse对象
                RpcResponse rpcResponse=new RpcResponse();
                rpcResponse.setData(res);
                rpcResponse.setStatusCode(1);
                rpcResponse.setMessage("success!");
                //返回给客户端
                objectOutputStream.writeObject(rpcResponse);
                objectOutputStream.flush();
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("error when invoking---");
            }
        }
    }

    public static void main(String[] args) {
        HelloService helloService=new HelloServiceImpl();
        RpcServer rpcServer=new RpcServer();
        //注册一个helloService服务
        rpcServer.register(helloService,8825);
    }

}
